import { Button, Checkbox, Collapse, ConfigProvider, Dropdown, MenuProps, Pagination, Popconfirm, Spin, Tag } from 'antd'
import { Table } from 'antd/lib'
import { getItem, hsHandleTableDateTime, initPageType, message, PERMISSIONS, usePageChange, USERRESULT } from '@hs-admin/utils'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { CloseOutlined, FileAddFilled } from '@ant-design/icons'
import CommonModal from '@/views/BatchQuery/components/CommonEditModal.tsx'
import { useAddBySearch } from '@/views/BatchQuery/components/AddBySearch.tsx'
import { useAddByImport } from '@/views/BatchQuery/components/AddByImport.tsx'
import { useAddByFavor } from '@/views/BatchQuery/components/AddByFavor.tsx'
import { useAddByQuery } from '@/views/BatchQuery/components/AddByQuery.tsx'
import { SelectDatesList } from '@/api/Database.ts'
import {
  cleanTheTableData,
  creatTableQuery,
  deleteDataItem,
  deleteTableQuery,
  exportRelTableData,
  exportTableData,
  getIds,
  getRelTables,
  getTopTables,
  queryData,
  queryRelDataTable
} from '@/api/batchQuery.ts'
import { getTableColumns } from '@/api/favor.ts'
import { ServerExportModal } from '@hs-server/components'
import './table.css'

const colorful = ['processing', 'cyan', 'geekblue', 'purple', 'magenta'] as const

const items: MenuProps['items'] = [
  {
    key: 'search',
    label: '搜索添加'
  },
  {
    key: 'list',
    label: '导入清单'
  },
  {
    key: 'favor',
    label: '导入收藏数据'
  },
  {
    key: 'query',
    label: '导入收藏筛选'
  }
]
const render = (obj: any) => (typeof obj === 'object' ? JSON.stringify(obj) : obj)

const useCheckFields = ({
  mainTableFields,
  relTables,
  setQuery,
  activeSubTable
}: {
  mainTableFields: Array<{
    label: string
    value: string
    defaultChecked: boolean
  }>
  relTables: Array<{
    label: string
    value: string
  }>
  setQuery: (value: Record<string, any>) => void
  activeSubTable: string
}) => {
  const [mainFields, setMainFields] = useState<Array<string>>([])

  const [refFields, setRelFields] = useState<
    Record<
      string,
      {
        enabled: boolean
        children: Array<{
          label: string
          value: string
          checked: boolean
        }>
      }
    >
  >({})

  useEffect(() => {
    setMainFields(mainTableFields.filter((it) => it.defaultChecked).map((it) => it.value))
  }, [mainTableFields])

  useEffect(() => {
    const relTableIds = relTables.map((it) => it.value)
    const obj: Record<
      string,
      {
        enabled: boolean
        children: Array<{
          label: string
          value: string
          checked: boolean
        }>
      }
    > = {}
    relTableIds.forEach((key) => {
      obj[key] = {
        enabled: false,
        children: []
      }
    })
    setRelFields(obj)
    relTableIds.forEach((key) => {
      getTableColumns(key).then((res: any) => {
        setRelFields((prevState) => ({
          ...prevState,
          [key]: {
            enabled: false,
            children: res
              .filter((it) => it.available)
              .map((item: any) => ({
                label: item.comment,
                value: item.name,
                checked: !!item.queryable
              }))
          }
        }))
      })
    })
  }, [relTables])

  useEffect(() => {
    setQuery({
      mainFields,
      refFields
    })
  }, [mainFields, refFields, setQuery])

  const [tableFields, setTableFields] = useState<any[]>([])

  useEffect(() => {
    const allRelTables = activeSubTable ? relTables.filter((it) => it.value === activeSubTable) : relTables

    const tableFields = []
    if (mainTableFields?.length && !activeSubTable) {
      tableFields.push({
        label: '所需字段',
        key: 'requiredField',
        children: (
          <div className="max-h-110 overflow-auto">
            <Checkbox.Group
              className="flex flex-col p-y-2 gap-1"
              value={mainFields}
              onChange={(values) => {
                setMainFields(values)
              }}
              options={mainTableFields}
            />
          </div>
        )
      })
    }
    if (relTables?.length) {
      tableFields.push({
        label: '关联数据',
        key: 'refTables',
        children: (
          <Collapse
            items={allRelTables.map((item) => ({
              key: item.value,
              label: (
                <div className="flex gap-2">
                  <Checkbox
                    checked={refFields[item.value]?.enabled}
                    onClick={(e) => {
                      e.stopPropagation()
                    }}
                    onChange={(e) => {
                      setRelFields((prevState) => ({
                        ...prevState,
                        [item.value]: {
                          enabled: e.target.checked,
                          children: prevState[item.value].children
                        }
                      }))
                    }}></Checkbox>
                  {item.label}
                </div>
              ),
              children:
                (refFields[item.value] && (
                  <Checkbox.Group
                    className="flex flex-col p-l"
                    value={refFields[item.value].children.filter((it) => it.checked).map((it) => it.value) ?? []}
                    options={refFields[item.value].children}
                    disabled={!refFields[item.value].enabled}
                    onChange={(values) => {
                      setRelFields((prevState) => ({
                        ...prevState,
                        [item.value]: {
                          enabled: prevState[item.value].enabled,
                          children: prevState[item.value].children.map((it) => ({
                            ...it,
                            checked: values.includes(it.value)
                          }))
                        }
                      }))
                    }}
                  />
                )) ??
                null
            }))}
          />
        )
      })
    }

    setTableFields(tableFields)
  }, [activeSubTable, mainFields, mainTableFields, refFields, relTables])

  return useMemo(
    () => ({
      CheckFields: (
        <ConfigProvider
          theme={{
            components: {
              Collapse: {
                padding: 0,
                borderRadiusLG: 0,
                lineType: 'none'
              }
            }
          }}>
          <Collapse items={tableFields} defaultActiveKey={['requiredField']} />
        </ConfigProvider>
      ),
      delRelTable: (key: string) => {
        setRelFields((prevState) => ({
          ...prevState,
          [key]: {
            ...prevState[key],
            enabled: false
          }
        }))
      }
    }),
    [tableFields]
  )
}

const initPage: initPageType = {
  current: 1,
  total: 0,
  pageSize: 50
}

const BatchQuery = () => {
  const [topTables, setTopTables] = useState<
    Array<{
      label: string
      id: string
      tableId: string
    }>
  >([])

  const [activeTables, setActiveTables] = useState({
    main: '',
    rel: ''
  })

  const activeQueryTable = activeTables.main
  const activeSubTable = activeTables.rel

  const [data, setData] = useState([])

  const activeTopTableId = topTables.find((it) => it.id === activeQueryTable)?.tableId ?? ''

  const keepIds = useRef<Record<string, string>>({})
  const allDataIds = useRef<Record<string, Array<string>>>({})

  const relTableIdsMap = useRef<Record<string, string>>({})

  const getFields = useCallback(
    async (page: number, pageSize: number) => {
      if (!activeQueryTable) throw 'no id'
      setData([])

      if (!activeSubTable) {
        allDataIds.current[activeQueryTable] = []
        const idRes = await getIds(activeQueryTable, {
          page,
          page_size: pageSize
        })
        const obj: Record<string, string> = {}
        const items = idRes.items
        const total = idRes.total ?? 0
        items.forEach((it) => {
          obj[it.data_id] = it.id
        })
        keepIds.current = obj
        const ids = items.map((it) => it.data_id)
        if (ids.length) {
          const res = await queryData(activeTopTableId, {
            page: 1,
            page_size: pageSize,
            ids,
            keywords: null,
            filters: []
          })
          setData(res.items)
          return total
        }
        return 0
      } else {
        let ids: string[]
        if (allDataIds.current[activeQueryTable]?.length) {
          ids = allDataIds.current[activeQueryTable]
        } else {
          const idRes = await getIds(activeQueryTable, {
            page: 1,
            page_size: 10000
          })
          ids = idRes.items.map((it) => it.data_id)
          allDataIds.current[activeQueryTable] = ids
        }
        const res = await queryRelDataTable(activeQueryTable, {
          ids,
          related_id: relTableIdsMap.current[activeSubTable],
          page,
          page_size: pageSize
        })
        setData(res.items)
        return res.total ?? 0
      }
    },
    [activeQueryTable, activeSubTable, activeTopTableId]
  )

  const { resetPageAndTriggerRequest, pagination, loading } = usePageChange(initPage, getFields)

  useEffect(() => {
    resetPageAndTriggerRequest()
  }, [resetPageAndTriggerRequest])

  const getTopTabs = () => {
    getTopTables().then((res) => {
      setTopTables(
        res.items.map((item: any) => ({
          label: item.release_item.data_item_product.name,
          id: item.id,
          tableId: item.release_item.id
        }))
      )
    })
  }

  const [queryOptions, setQueryOptions] = useState<{
    mainFields: any[]
    refFields: Record<string, any>
  }>({
    mainFields: [],
    refFields: {}
  })

  const [allTables, setAllTables] = useState<MenuProps['items']>([])

  const [mainTableFields, setMainTableFields] = useState<
    Array<{
      label: string
      value: string
      defaultChecked: boolean
      unique: boolean
    }>
  >([])

  const [relTables, setRelTables] = useState<
    Array<{
      label: string
      value: string
    }>
  >([])

  const { children: childrenSearch, ...restSearch } = useAddBySearch(
    activeQueryTable,
    activeTopTableId,
    mainTableFields
      .filter((item) => item.defaultChecked)
      .map((item) => ({
        title: item.label,
        key: item.value,
        dataIndex: item.value,
        ellipsis: true,
        render,
        width: 230
      })),
    resetPageAndTriggerRequest
  )
  const refSearch = useRef<{
    showModal: () => void
  } | null>(null)
  const { children: childrenImport, ...restImport } = useAddByImport(
    activeQueryTable,
    resetPageAndTriggerRequest,
    mainTableFields.filter((item) => item.unique)
  )
  const refImport = useRef<{
    showModal: () => void
  } | null>(null)

  const { children: childrenFavor, ...restFavor } = useAddByFavor(
    activeQueryTable,
    activeTopTableId,
    mainTableFields
      .filter((item) => item.defaultChecked)
      .map((item) => ({
        title: item.label,
        key: item.value,
        dataIndex: item.value,
        ellipsis: true,
        render,
        width: 230
      })),
    resetPageAndTriggerRequest
  )
  const refFavor = useRef<{
    showModal: () => void
  } | null>(null)

  const { children: childrenQuery, ...restQuery } = useAddByQuery(activeQueryTable, activeTopTableId, resetPageAndTriggerRequest)
  const refQuery = useRef<{
    showModal: () => void
  } | null>(null)

  const modals = {
    search: refSearch.current,
    list: refImport.current,
    favor: refFavor.current,
    query: refQuery.current
  }

  useEffect(() => {
    getTopTabs()

    SelectDatesList().then((res) => {
      res.map((item: any) => {
        item.key = item.id
        item.label = item.name
        item.children = item.items.map((its: any) => {
          its.key = its.id
          its.label = its.data_item_product.name
          return its
        })
      })
      setAllTables(res)
    })
  }, [])

  useEffect(() => {
    setActiveTables((prevState) => {
      let main = prevState.main
      let rel = prevState.rel
      if (!topTables.map((it) => it.id).includes(main)) {
        main = topTables[0]?.id ?? ''
        rel = ''
      }
      return {
        main,
        rel
      }
    })
  }, [topTables])

  useEffect(() => {
    setMainTableFields([])
    setRelTables([])
    if (activeTopTableId) {
      getTableColumns(activeTopTableId).then((res) => {
        setMainTableFields(
          res
            .filter((it) => it.available)
            .map((item: any) => ({
              label: item.comment,
              value: item.name,
              defaultChecked: !!item.queryable,
              unique: item.unique
            }))
        )
      })
      getRelTables(activeTopTableId).then((res) => {
        const obj = {}
        res.items.forEach((it) => {
          obj[it.right_item.id] = it.id
        })
        relTableIdsMap.current = obj
        setRelTables(
          res.items.map((it: any) => ({
            label: it.right_item.data_item_product.name,
            value: it.right_item.id
          }))
        )
      })
    }
  }, [activeTopTableId])

  useEffect(() => {
    const secondRelTables = Object.entries(queryOptions.refFields)
      .filter(([_, v]) => v.enabled)
      .map(([k, _]) => k)
    if (activeSubTable) {
      if (secondRelTables.length) {
        if (!secondRelTables.includes(activeSubTable)) {
          setActiveTables((prevState) => ({
            ...prevState,
            rel: ''
          }))
        }
      } else {
        setActiveTables((prevState) => ({
          ...prevState,
          rel: ''
        }))
      }
    }
  }, [activeSubTable, queryOptions.refFields])

  const { CheckFields, delRelTable } = useCheckFields({
    mainTableFields,
    relTables,
    setQuery: setQueryOptions,
    activeSubTable
  })

  let columns: { title: string; key: string; dataIndex: string; render: (obj: any, row: any) => any; ellipsis?: boolean }[] = []
  if (queryOptions.mainFields?.length) {
    columns = mainTableFields
      .filter((item) => queryOptions.mainFields.includes(item.value))
      .map((item) => ({
        title: item.label,
        key: item.value,
        dataIndex: item.value,
        ellipsis: true,
        width: 200,
        render
      }))
    columns.unshift({
      title: '',
      key: 'option',
      dataIndex: 'option',
      width: 80,
      fixed: 'left',
      render: (_, row) => (
        <Dropdown
          trigger={['click']}
          menu={{
            items: [
              {
                key: 'del',
                label: (
                  <Button
                    type="link"
                    onClick={() => {
                      const itemId = keepIds.current[row.id]
                      if (itemId)
                        deleteDataItem(activeQueryTable, itemId).then(() => {
                          message.success('删除成功')
                          resetPageAndTriggerRequest()
                        })
                    }}>
                    删除本行及关联的数据
                  </Button>
                )
              }
            ]
          }}>
          <Button type="link">操作</Button>
        </Dropdown>
      )
    })
  }
  if (activeSubTable) {
    columns = (queryOptions.refFields[activeSubTable]?.children.filter((it) => it.checked) ?? []).map((item) => ({
      title: item.label,
      key: item.value,
      dataIndex: item.value,
      ellipsis: true,
      width: 200,
      render
    }))
  }

  const { DoExportModal, canExportCount, promptAndSetFileName, setFileName, sorryWarning } = ServerExportModal()

  const exportColumns =
    columns
      ?.filter((it) => it.title)
      .map((it) => ({
        field: it.key,
        name: it.title
      })) ?? []

  const exportUrl = activeSubTable
    ? async (name: string) => {
        const idRes = await queryRelDataTable(activeQueryTable, {
          ids: allDataIds.current[activeQueryTable],
          related_id: relTableIdsMap.current[activeSubTable],
          page: 1,
          page_size: 10000
        })
        const ids = idRes.items?.map((it) => it.id) ?? []
        if (!ids.length) {
          message.error('无数据可导出')
          throw '无数据'
        }
        return await exportRelTableData(activeSubTable, {
          columns: exportColumns,
          filename: name,
          query: {
            keywords: null,
            filters: [],
            relation: null,
            ids,
            page: 1,
            page_size: 10000
          }
        })
      }
    : (name: string) =>
        exportTableData(activeQueryTable, {
          columns: exportColumns,
          filename: name
        })

  const permissions = getItem(PERMISSIONS) || []

  return (
    <div className="grid grid-cols-[auto_1fr] gap-4 p6 bg-white w-full h-full overflow-hidden">
      <div className="flex flex-col gap-8 w-80 overflow-hidden">
        <Dropdown
          menu={{
            items: allTables,
            onClick: ({ key }) => {
              creatTableQuery({ release_item_id: key }).then(() => {
                message.success('创建成功')
                getTopTabs()
              })
            }
          }}>
          <Button type="primary">创建查询</Button>
        </Dropdown>
        <div className="flex-1 border-1 border-solid border-gray-200 bg-gray-100 overflow-auto">{CheckFields}</div>
      </div>
      <div className="p-2 flex flex-col gap-4 overflow-hidden">
        <div className="flex gap-4 overflow-auto">
          {topTables.map((it, index) => (
            <Tag
              color={colorful[index % 5]}
              key={it.id}
              closable={true}
              style={{ userSelect: 'none', filter: activeQueryTable === it.id ? '' : 'grayscale(100%) contrast(80%)' }}
              onClick={() => {
                if (activeQueryTable !== it.id) {
                  setActiveTables({
                    main: it.id,
                    rel: ''
                  })
                }
              }}
              closeIcon={
                <Popconfirm
                  title="确认删除？"
                  onConfirm={() => {
                    deleteTableQuery(it.id).then(() => {
                      message.success('删除成功')
                      getTopTabs()
                    })
                  }}>
                  <CloseOutlined />
                </Popconfirm>
              }
              onClose={(e) => {
                e.preventDefault()
              }}>
              <span className="px-8 leading-8 hover:cursor-pointer">{it.label}</span>
            </Tag>
          ))}
        </div>
        <div className="flex-1 overflow-hidden flex flex-col gap-4">
          <div className="flex gap-4 items-center h-16">
            <Tag
              color="green"
              style={{
                userSelect: 'none',
                filter: activeSubTable === '' ? '' : 'grayscale(100%) contrast(80%)'
              }}
              onClick={() => {
                setActiveTables((prevState) => ({
                  ...prevState,
                  rel: ''
                }))
              }}>
              <span className="px-8 leading-8 hover:cursor-pointer">主数据</span>
            </Tag>
            <div className="flex gap-2 items-center overflow-auto whitespace-nowrap">
              关联数据：
              {relTables
                .filter((it) => queryOptions.refFields[it.value]?.enabled)
                .map((it, index) => (
                  <Tag
                    color={colorful[index % 5]}
                    key={it.value}
                    closable={true}
                    style={{
                      userSelect: 'none',
                      filter: activeSubTable === it.value ? '' : 'grayscale(100%)  contrast(80%)'
                    }}
                    onClick={() => {
                      setActiveTables((prevState) => ({
                        ...prevState,
                        rel: it.value
                      }))
                    }}
                    onClose={() => {
                      delRelTable(it.value)
                    }}>
                    <span className="px-8 leading-8 hover:cursor-pointer">{it.label}</span>
                  </Tag>
                ))}
            </div>
          </div>
          {activeQueryTable && (
            <div className="flex justify-between">
              <div className="flex gap-4">
                {!activeSubTable && (
                  <Dropdown
                    menu={{
                      items,
                      onClick: (e) => {
                        modals[e.key]?.showModal()
                      }
                    }}>
                    <Button icon={<FileAddFilled />}>添加清单</Button>
                  </Dropdown>
                )}
              </div>
              <div className="flex gap-4">
                <Popconfirm
                  title="确定清空？"
                  onConfirm={() => {
                    cleanTheTableData(activeQueryTable).then(() => {
                      message.success('清空成功')
                      resetPageAndTriggerRequest()
                    })
                  }}>
                  <Button>清空内容</Button>
                </Popconfirm>
                {permissions.includes('sg.export.limit.20000') && (
                  <div>
                    <Button
                      disabled={!pagination.total}
                      type="primary"
                      onClick={() => {
                        if (!exportColumns.length) {
                          message.error('没有选择字段')
                          return
                        }
                        const defaultFileName = `${hsHandleTableDateTime(Date.now())} ${getItem(USERRESULT)?.name} 导出`
                        if (pagination.total > canExportCount) {
                          sorryWarning(`全部数据${pagination.total}条，今日导出剩余${canExportCount}条，无法导出`)
                        } else if (pagination.total > 10000) {
                          sorryWarning(`导出超过单次数量限制(10000条)，无法导出`)
                        } else if (pagination.total > 5000) {
                          promptAndSetFileName(defaultFileName, exportUrl)
                        } else {
                          setFileName(defaultFileName, exportUrl)
                        }
                      }}>
                      导出当前
                    </Button>
                    <p>今日还能导出{canExportCount}条</p>
                  </div>
                )}
              </div>
            </div>
          )}
          <Spin spinning={loading}>
            {activeQueryTable ? (
              activeSubTable ? (
                <div className="flex items-center gap-4 w-full">
                  <Button
                    type="primary"
                    disabled={pagination.current === 1}
                    onClick={() => {
                      pagination.onChange(pagination.current - 1)
                    }}>
                    上一页
                  </Button>
                  <span>
                    第{pagination.current}页 / 共{Math.ceil(pagination.total / pagination.pageSize)}页
                  </span>
                  <Button
                    type="primary"
                    disabled={pagination.current * pagination.pageSize >= pagination.total}
                    onClick={() => {
                      pagination.onChange(pagination.current + 1)
                    }}>
                    下一页
                  </Button>
                  <span>
                    每页{pagination.pageSize}条，共{pagination.total}条
                  </span>
                </div>
              ) : (
                <Pagination {...pagination} showTotal={(total) => `每页${pagination.pageSize}条，共${total}条`} />
              )
            ) : null}
          </Spin>
          <Table className="flex-1" loading={loading} pagination={false} columns={columns} dataSource={data} rowKey="id" />
        </div>
      </div>
      {DoExportModal}
      <CommonModal ref={refSearch} {...restSearch} footer={null}>
        {childrenSearch}
      </CommonModal>
      <CommonModal ref={refImport} {...restImport}>
        {childrenImport}
      </CommonModal>
      <CommonModal ref={refFavor} {...restFavor} footer={null}>
        {childrenFavor}
      </CommonModal>
      <CommonModal ref={refQuery} {...restQuery} footer={null}>
        {childrenQuery}
      </CommonModal>
    </div>
  )
}

export default BatchQuery
